/**
 * @classDefinition The PersistableClass module includes the methods necessary
 * to define a custom persistable class.
 */
var PersistableClass = {
    
    /**
     * The hash of all persistable class currently known by ObjectThought.
     */
    allPersistableTypes: new Hash(),
    
    /**
     * Creates a new persistable class.
     * 
     * PersistableClass.create is similar to prototype's Class.create (in fact, 
     * Class.create is called internally for you).
     * 
     * @param {String} singularName         The singular name of the class, as in "Person".
     * @param {String} pluralName           The plural name of the class, as in "People"
     * @param {Function} classDefinition    A method that is called after the new class has been created
     *                                      and is bound to the PersistableClass module; from here, you can
     *                                      call any method on PersistableClass, with the new class as the subject
     *                                      of all of the calls.
     * @param {Object, Hash} classBody
     * 
     * @return {Class} The new class.
     */
    create: function(singularName, pluralName, classDefinition, classBody)
    {
        // define the class and place it in the global namespace
        var persistableClass = PersistableClass.__currentClass__ = window[singularName] = Class.create(classBody);

        // basic class setup
        persistableClass.singularName = singularName;
        persistableClass.pluralName = pluralName;
        
        persistableClass.__fieldNames = [];

        Object.extend(persistableClass, PersistableClass.ClassMethods);
        persistableClass.addMethods(PersistableClass.InstanceMethods);
        
        PersistableClass.allPersistableTypes.set(persistableClass.singularName, persistableClass);

        try
        {
            // call the class definition in the context of PersistableClass
            classDefinition = classDefinition.bind(PersistableClass);
            classDefinition();
        }
        finally
        {
            PersistableClass.__currentClass__ = null;
        }
        
        return persistableClass;
    },
    
    
    /**
     * Designates the given field name as the identity field for this
     * class.  The identity field is special, and is mostly managed by
     * ObjectThought.
     * 
     * After returning, the current class (@see PersistableClass.create) will
     * have a new property named with the given string.  It's initial value
     * will be null.
     * 
     * This method can only be called in the context of a class definition
     * initiated by @see PersistableClass.create.
     * 
     * @param {String} identifierFieldName  The name of this class's identity field.
     */
    identifiedBy: function(identifierFieldName)
    {
        if (PersistableClass.__currentClass__ == null) 
            throw new Error("hasField may only be called in the context of class definition.");
        
        var persistableClass = PersistableClass.__currentClass__;
        
        persistableClass.__identifierFieldName = identifierFieldName;
        
        // define the identifier field
        persistableClass.prototype[identifierFieldName] = null;
    },
    
    /**
     * Creates and describes a new persistable field on the current class.  The field
     * will be named with the given fieldName. 
     * 
     * @param {String} fieldName    The name of the field.
     * @param {Hash} fieldOptions   Persistence options applying to this field.
     */
    hasField: function(fieldName, fieldOptions)
    {
        if (PersistableClass.__currentClass__ == null) 
            throw new Error("hasField may only be called in the context of class definition.");
        
        var persistableClass = PersistableClass.__currentClass__;
        
        // define the field and register with __fieldNames for the class
        persistableClass.__fieldNames.push(fieldName);
        persistableClass.prototype[fieldName] = null;
        
        // TODO: process the field options
    },
    
    
    
    
    /**
     * These are the class methods extended onto each persistable class.
     */
    ClassMethods:
    {
        getPersistableIdentifierFieldName: function()
        {
            return this.__identifierFieldName;
        },
        getPersistableFieldNames: function()
        {
            return this.__fieldNames.clone();
        },
    },
    
    /**
     * These are instance methods added to every persistable class instance.
     */
    InstanceMethods:
    {
        getPersistableIdentifier: function()
        {
            return this[this.constructor.__identifierFieldName];
        },
        setPersistableIdentifier: function(identifier)
        {
            this[this.constructor.__identifierFieldName] = identifier;
        },
        
        getPersistableFieldValues: function()
        {
            return this.constructor.__fieldNames.collect(function(fieldName)
            {
                return this[fieldName];
            }, this);
        }
    }
};